
#include "khan.hpp"
#include "cmd_mng.hpp"
#include "util.hpp"

static const std::string OPT_START = "(";
static const std::string OPT_END   = ")";
static const std::string MULTI_OPT = "|";

static const std::string CMD_LINE_DELIM = " \t";
static const std::string CMD_DELIM = " \t\r\n";
static const std::string OPT_DELIM = " ()|\r\n";
static const std::string HELP_DELIM = "\r\n";

#define SHOW_HELP   "show system information\n"
#define NO_HELP     "negate a command or set its defaults\n"

#define XSG_HELP    "xener signalling gateway system\n"

#define CRTE_OSP_HELP   "Create Own Signalling Point\n"
#define DIS_SLK_HELP    "Display Signalling Link Information\n"
#define CRTE_SLK_HELP   "Create Signalling Link\n"
#define DEL_SLK_HELP    "Delete Signalling Link\n"

#define OPC_HELP    "Own Signaling Point Code\n"
#define OSPN_HELP   "Own Signaling Point Name\n"
#define ASPN_HELP   "Adjacent Signaling Point Name\n"
#define SLC_HEP     "Signalling Link Code\n"
#define ST_HELP     "Signalling Terminal Number\n"
#define TRK_HELP    "Trunk Number\n"
#define TS_HELP     "Time Slot Number\n"

#define MTP3_VARIANT_HELP "MTP L3 Protocol Variant Type\n"
#define UNKNOWN_HELP    "Unkown\n"
#define ITU_BLUE_HELP   "ITU_BLUE\n"
#define ITU_WHITE_HELP  "ITU_WHITE\n"
#define ITU_CHINA_HELP  "ITU_CHINA\n"
#define TTC_HELP        "TTC\n"
#define JTT_HELP        "JTT\n"
#define ANSI_88_HELP    "ANSI_88\n"
#define ANSI_91_HELP    "ANSI_91\n"
#define ANSI_96_HELP    "ANSI_96\n"

#define SP_TYPE_HELP    "Signaling Point Type\n"
#define SEP_HELP    "Signaling End Point\n"
#define STP_HELP    "Signal Transfer Point\n"

#define NI_HELP "Network Indicator\n"
#define SP_INT_HELP "International\n"
#define SP_RSV_HELP "Reserved\n"
#define SP_NAT_HELP "National\n"
#define SP_LOC_HELP "Local\n"

#if 0
std::string tmp("ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>");
std::string tmp2( IP_HSTR "IP destination prefix (e.g. 10.0.0.0/8)\n" "IP gateway address\n"
            "IP gateway interface name\n" "Null interface\n" "Distance value for this route\n");
#endif 

#define IP_HSTR   "ip information\n"
#define IP_ROUTE_HELP "Establish static routes\n"
#define IF_HELP "netowrk interface\n"
#define MULTICAST_HELP "multicast\n"
#define DST_IP_HELP "destination ip address\n"
#define NULL_IF_HELP "null interface\n"
#define PROT_HELP "port number\n"
#define TMP_HELP "tmp string\n"

std::string tst_cmd_1("ip (route|interface|MULTICAST) (A.B.C.D|null0|<30-50>|HOSTNAME) (good|god)");
std::string tst_hlp_1(IP_HSTR IP_ROUTE_HELP IF_HELP MULTICAST_HELP DST_IP_HELP NULL_IF_HELP 
        PROT_HELP TMP_HELP TMP_HELP TMP_HELP);

int tst_function(vty_ptr vty, const std::string& command, string_vector& args);
int tst_function2(vty_ptr vty, const std::string& command, string_vector& args);

void print_cmd_desc(cmd_list_iterator begin, cmd_list_iterator end, bool is_exec) 
{
    cmd_list_iterator iter = begin;
    for (; iter != end; iter++) {
        printf("%-10s\t%s\n", (*iter)->get_cmd().c_str(), (*iter)->get_help().c_str());
    }
    if (is_exec)
        printf("<CR>\n");
}

void tst_parsing();
void tst_parsing2();

int main()
{
    tst_parsing2();

    return 0;
}

void tst_parsing2()
{
    bool ret = false, is_exec = false;
    cmd_mode_ptr modeptr;
    cmd_ptr ptr;
    cmd_list_t  cmdlist;
    cmd_list_iterator iter;


    cmd_mng_ptr cmdmng = cmd_mng::instance();
    cmdmng->add_mode("EXEC", "#");
    cmdmng->find_mode("EXEC", modeptr);

    ptr= modeptr->get_root();
    cmdmng->add_command("EXEC", "tst (mtp2|m2pa) <0x10-0x30>", "tst\ntst\ntst\ntst\n", 
            tst_function);

    ret = cmdmng->excute_command("t m2p 0x20");
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();

}

void tst_parsing()
{
    bool ret = false, is_exec = false;
    cmd_mode_ptr modeptr;
    cmd_ptr ptr;
    cmd_list_t  cmdlist;
    cmd_list_iterator iter;

    cmd_mng_ptr cmdmng = cmd_mng::instance();
    cmdmng->add_mode("EXEC", "#");
    cmdmng->find_mode("EXEC", modeptr);

#if 0
    ptr= modeptr->get_root();
    cmdmng->add_command("EXEC", "ip (route|MULTICAST|TST) good (hello|byebye)", "TST\n", tst_function);

    int num = ptr->find_children(exact_match, "ip", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 1);

    ptr = *(cmdlist.begin());
    cmdlist.clear();
    num = ptr->find_children("rou", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 2);
#endif

    cmdmng->add_command("EXEC", tst_cmd_1, tst_hlp_1, tst_function2);

    /*
    ret = cmdmng->describe_command("", cmdlist, true, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();    */


    ret = cmdmng->describe_command("i rou ", cmdlist, false, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();

    ret = cmdmng->describe_command("i rou", cmdlist, true, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();


    ret = cmdmng->describe_command("i rou 31", cmdlist, false, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();

    ret = cmdmng->describe_command("i rou 31", cmdlist, true, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();

    ret = cmdmng->describe_command("i rou 192.168 ", cmdlist, false, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();

    ret = cmdmng->describe_command("i rou 192.168 g", cmdlist, false, is_exec);
    assert(ret == true);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();

    ret = cmdmng->describe_command("i rou 192.168 g", cmdlist, true, is_exec);
    assert(ret == false);
    print_cmd_desc(cmdlist.begin(), cmdlist.end(), is_exec);
    cmdlist.clear();


    ret = cmdmng->excute_command("ip hhgood g b");
    assert(ret == false);
    ret = cmdmng->excute_command("ip rou g ");
    assert(ret == false);
    ret = cmdmng->excute_command("ip rou  null god");
    assert(ret == true);
    ret = cmdmng->excute_command("ip rou  hull goo");
    assert(ret == true);
    ret = cmdmng->excute_command("ip rou  20 goo");
    assert(ret == true);
    ret = cmdmng->excute_command("ip rou  192.26 g");
    assert(ret == false);
    ret = cmdmng->excute_command("ip rou  19 good");
    assert(ret == true);
    ret = cmdmng->excute_command("ip rou  192.26 ");
    assert(ret == false);
    ret = cmdmng->excute_command("ip rou  31 god ");
    assert(ret == true);

#if 0
    ptr= modeptr->get_root();
    cmdlist.clear();
    num = ptr->find_children(exact_match, "ip", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 1);

    ptr = *(cmdlist.begin());
    cmdlist.clear();
    num = ptr->find_children("rou", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 2);

    ptr = *(cmdlist.begin());
    cmdlist.clear();
    num = ptr->find_children("35", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 2);

    ptr = *(cmdlist.begin());
    cmdlist.clear();
    num = ptr->find_children("g", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 1);

    cmdlist.clear();
    num = ptr->find_children("234", cmdlist);
    PDBG("num: %d\n", num);
    assert(num == 0);
#endif


    
    //cmdmng->(root, tst_cmd_1, tst_hlp_1);

#if 0
    make_tree("osp <1-16777215> OPSN ni (int|rsv|nat|loc) "
            " variant (unkown|itu_blue|itu_white|itu_china|ttc|jtt|ansi_88|ansi_91|ansi_96)"
            " type (sep|stp)",
            CRTE_OSP_HELP OPC_HELP OSPN_HELP
            NI_HELP SP_INT_HELP SP_RSV_HELP SP_NAT_HELP SP_LOC_HELP
            MTP3_VARIANT_HELP
            UNKNOWN_HELP ITU_BLUE_HELP ITU_WHITE_HELP ITU_CHINA_HELP TTC_HELP JTT_HELP
            ANSI_88_HELP ANSI_91_HELP ANSI_96_HELP
            SP_TYPE_HELP SEP_HELP STP_HELP
            );

    make_tree("osp <1-16777215> OPSN (int|rsv|nat|loc) "
            " (unkown|itu_blue|itu_white|itu_china|ttc|jtt|ansi_88|ansi_91|ansi_96)"
            " (sep|stp)",
            CRTE_OSP_HELP OPC_HELP OSPN_HELP
            SP_INT_HELP SP_RSV_HELP SP_NAT_HELP SP_LOC_HELP
            UNKNOWN_HELP ITU_BLUE_HELP ITU_WHITE_HELP ITU_CHINA_HELP TTC_HELP JTT_HELP
            ANSI_88_HELP ANSI_91_HELP ANSI_96_HELP
            SEP_HELP STP_HELP
            );
#endif 
};

int tst_function2(vty_ptr vty, const std::string& command, string_vector& args)
{
    PDBG("func2: %s\n", command.c_str());
    search_vector(args.begin(), args.end(), print_string);
    return 0;
}

int tst_function(vty_ptr vty, const std::string& command, string_vector& args)
{
    PDBG("func1: %s\n", command.c_str());
    search_vector(args.begin(), args.end(), print_string);
    return 0;
}
